package com.qk.common.util;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.ListObjectsV2Result;
import com.aliyun.oss.model.OSSObjectSummary;
import com.qk.common.property.AliYunOSSProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Date:2025/10/10
 * Author:zxc
 * Description
 */
@Slf4j
@Component
public class AliYunOSSOperators {

    private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";
    private static final String BUCKET_NAME = "java-web-zxc-2025";
    private static final String REGION = "cn-beijing";
@Autowired
private AliYunOSSProperties aliYunOSSProperties;

    /**
     * 上传文件到OSS
     */
    public String upload(byte[] content, String originalFilename) throws Exception {
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 构建文件路径（日期目录 + 随机文件名）
        String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = dir + "/" + newFileName;

        // 获取配置参数
        String endpoint = aliYunOSSProperties.getEndpoint();
        String bucketName = aliYunOSSProperties.getBucketName();
        String region = aliYunOSSProperties.getRegion();

        // 创建OSS客户端
        OSS ossClient = createOssClient(endpoint, credentialsProvider, region);

        try {
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
        } finally {
            ossClient.shutdown(); // 确保客户端关闭
        }

        // 构建文件访问URL
        return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
    }

    /**
     * 遍历OSS Bucket中的文件（支持指定前缀，模拟目录遍历）
     * @param keyPrefix 可选，文件前缀（如 "2024/10/" 表示遍历该目录下的文件，null则遍历所有文件）
     * @return 文件信息列表（包含文件名、大小、修改时间等）
     */
    public List<OSSObjectSummary> listFiles(String keyPrefix) throws Exception {
        // 获取配置参数
        String endpoint = aliYunOSSProperties.getEndpoint();
        String bucketName = aliYunOSSProperties.getBucketName();
        String region = aliYunOSSProperties.getRegion();
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSS客户端
        OSS ossClient = createOssClient(endpoint, credentialsProvider, region);

        try {
            // 构建列举请求（支持前缀筛选）
            ListObjectsV2Result result;
            if (keyPrefix != null && !keyPrefix.isEmpty()) {
                // 遍历指定前缀的文件（如目录）
                result = ossClient.listObjectsV2(bucketName, keyPrefix);
            } else {
                // 遍历Bucket中所有文件
                result = ossClient.listObjectsV2(bucketName);
            }

            // 返回文件摘要列表（包含文件名、大小等信息）
            return result.getObjectSummaries();

        } finally {
            if (ossClient != null) {
                ossClient.shutdown(); // 确保客户端关闭
            }
        }
    }

    /**
     * 重载方法：默认遍历Bucket中所有文件（无需指定前缀）
     */
    public List<OSSObjectSummary> listFiles() throws Exception {
        return listFiles(null);
    }

    /**
     * 批量删除OSS中的文件
     * @param objectNames 要删除的文件路径列表（如 ["2025/10/11/xxx.jpg", "image/logo.png"]）
     * @return 成功删除的文件路径列表
     */
    public List<String> batchDeleteFiles(List<String> objectNames) throws Exception {
        // 获取配置参数
        String endpoint = aliYunOSSProperties.getEndpoint();
        String bucketName = aliYunOSSProperties.getBucketName();
        String region = aliYunOSSProperties.getRegion();
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSS客户端
        OSS ossClient = createOssClient(endpoint, credentialsProvider, region);

        try {
            // 构建批量删除请求
            DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName)
                    .withKeys(objectNames) // 设置要删除的文件列表
                    .withEncodingType("url"); // 启用URL编码（避免特殊字符问题）

            // 执行删除并获取结果
            DeleteObjectsResult deleteResult = ossClient.deleteObjects(deleteRequest);
            List<String> deletedObjects = deleteResult.getDeletedObjects();

            // 解码并返回成功删除的文件路径
            List<String> decodedDeletedObjects = new ArrayList<>();
            for (String obj : deletedObjects) {
                try {
                    decodedDeletedObjects.add(URLDecoder.decode(obj, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    // 编码异常时，直接添加原始值（避免中断流程）
                    decodedDeletedObjects.add(obj);
                    e.printStackTrace();
                }
            }
            return decodedDeletedObjects;

        } finally {
            if (ossClient != null) {
                ossClient.shutdown(); // 确保客户端关闭
            }
        }
    }

    /**
     * 封装OSS客户端创建逻辑（复用代码，减少冗余）
     */
    private OSS createOssClient(String endpoint, EnvironmentVariableCredentialsProvider credentialsProvider, String region) {
        ClientBuilderConfiguration clientConfig = new ClientBuilderConfiguration();
        clientConfig.setSignatureVersion(SignVersion.V4); // 使用V4签名算法
        return OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientConfig)
                .region(region)
                .build();
    }
}
